package code.example.base.cpu.iostate.state1;

import code.example.tool.FixedThreadPool;
import code.example.tool.LogFactory;

import java.io.FileOutputStream;
import java.io.OutputStream;

/**
 * 启动脚本：java -cp lib/*:*.jar  code.example.base.cpu.iostate.state1.TestIOState1
 *  环境： 100条线程，向100个文件，不断的写文件,每次写入1k数据，主机8核cpu。
 *  现象：   iostat :%util 100%
 *           iostat :%iowait 90%
 *           线程状态：java.io.FileOutputStream.write(Native Method): java.lang.Thread.State: RUNNABLE
 *           磁盘写入时间：一次写入时间（最长的） 200ms以上，
 *           vmstat: system cs 0-1。
 *                   r队列:1-3。
 *                   b队列:99-100。
 *                   cpu us :1%左右。
 *                   cpu sy: 6%左右。
 *                   cpu wa: 90%。
 *  表明：  磁盘io等待时间过长。
 *          性能瓶颈在IO写入上。
 *          cpu us :1%左右，用户线程执行占用很少的CPU，写入任务交给CPU内核，进行IO操作。
 *          cpu sy: 6%左右，cpu切换线程上下文：
 *                               1.100个线程轮流分配cpu时间片上下文切换,(这部分占用cpu应该很小)
 *                               2.java 中write 方法调用后，磁盘写入时，由cpu与磁盘速度差异，cpu把写入任务交给DMA总线，
 *                               把写入线程状态表现为Runnable（操作系统中线程状态  为D(TASK_UNTNTERRUPTIBLE) ）但不可获得cpu时间片，把cpu时间片分给别的线程，
 *                               磁盘写入完成后，设置中断唤醒线程，再继续执行。
 *
 *         cpu wa: 90%  ，等待IO操作时间
 *         cpu load 过高： 线程都在Runnable状态（TOP 命令中显示为 D (TASK_UNTNTERRUPTIBLE)），需要等待IO完成后，才能分配cpu(即不能立即获得cpu时间片，需要等待IO完成，所以cpu use time 不高)。
 *                         load值=R(运行的+可运行的)+D（等待IO的） ,所以load 高，cpu低。
 *         
 *
 */
public class TestIOState1 {
    public void testState(String fileName){
        try {
            byte []data = new byte [1024];
            for(int i=0;i<1024;i++){
                data[i]=0;
            }
            while(true){
                OutputStream os = new FileOutputStream(fileName);
                for(int i=0;i<10000;i++){
                    long startTime = System.currentTimeMillis();
                    os.write(1);
                    os.flush();
                    long useTime = System.currentTimeMillis() - startTime;
                    if(useTime >100){
                        LogFactory.getLog().info("write byte use time:"+useTime);
                    }
                }
                os.close();
            }

        }catch (Exception e){
            e.printStackTrace();
        }
    }
    public void test(){
        FixedThreadPool fixedThreadPool = new FixedThreadPool(8);
        for(int i=0;i<8;i++){
            final int id = i;
            fixedThreadPool.execute(new Runnable() {
                @Override
                public void run() {
                    testState("iostate0.context");
                }
            });

        }
    }
    public static void main(String args []){
        TestIOState1 testIOState = new TestIOState1();
        testIOState.test();
    }
}
